﻿//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
//
// C# Port port by: Lars Brubaker
//                  larsbrubaker@gmail.com
// Copyright (C) 2007-2011
//
// Permission to copy, use, modify, sell and distribute this software 
// is granted provided this copyright notice appears in all copies. 
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
//
// Class StyledTypeFace.cs
//
//----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;

using AGG;
using AGG.Transform;
using AGG.VertexSource;

namespace AGG.Font
{
    public class StyledTypeFace
    {
        public StyledTypeFace(TypeFace typeFace, double emSizeInPoints)
        {
            this.typeFace = typeFace;
            EmSizeInPoints = emSizeInPoints;
        }

        TypeFace typeFace;

        const int PointsPerInch = 72;
        const int PixelsPerInch = 96;

        double emSizeInPixels;
        double currentEmScalling;
        bool flatenCurves = true;

        /// <summary>
        /// <para>If true the font will have it's curves flattened to the current point size when retrieved.</para>
        /// <para>You may want to disable this so you can flaten the curve after other transforms have been applied,</para>
        /// <para>such as skewing or scalling.  Rotation and Translation will not alter how a curve is flattened.</para>
        /// </summary>
        public bool FlatenCurves
        {
            get
            {
                return flatenCurves;
            }

            set
            {
                flatenCurves = value;
            }
        }

        /// <summary>
        /// Sets the Em size for the font in pixels.
        /// </summary>
        public double EmSizeInPixels
        {
            get
            {
                return emSizeInPixels;
            }

            set
            {
                emSizeInPixels = value;
                currentEmScalling = emSizeInPixels / typeFace.UnitsPerEm;
            }
        }

        /// <summary>
        /// Sets the Em size for the font assuming there are 72 points per inch and there are 96 pixels per inch.
        /// </summary>
        public double EmSizeInPoints
        {
            get
            {
                return emSizeInPixels / PixelsPerInch * PointsPerInch;
            }

            set
            {
                EmSizeInPixels = value / PointsPerInch * PixelsPerInch;
            }
        }

        public double AscentInPixels
        {
            get
            {
                return typeFace.Ascent * currentEmScalling;
            }
        }

        public double DescentInPixels
        {
            get
            {
                return typeFace.Descent * currentEmScalling;
            }
        }

        public double XHeightInPixels
        {
            get
            {
                return typeFace.X_height * currentEmScalling;
            }
        }

        public double CapHeightInPixels
        {
            get
            {
                return typeFace.Cap_height * currentEmScalling;
            }
        }

        public rect_d BoundingBoxInPixels
        {
            get
            {
                rect_d pixelBounds = new rect_d(typeFace.BoundingBox);
                pixelBounds *= currentEmScalling;
                return pixelBounds;
            }
        }

        public double UnderlineThicknessInPixels
        {
            get
            {
                return typeFace.Underline_thickness * currentEmScalling;
            }
        }

        public double UnderlinePositionInPixels
        {
            get
            {
                return typeFace.Underline_position * currentEmScalling;
            }
        }

        public IVertexSource GetGlyphForCharacter(char character)
        {
            // scale it to the correct size.
            IVertexSource sourceGlyph = typeFace.GetGlyphForCharacter(character);
            Affine glyphTransform = Affine.NewIdentity();
            glyphTransform *= Affine.NewScaling(currentEmScalling);
            IVertexSource characterGlyph = new VertexSourceApplyTransform(sourceGlyph, glyphTransform);

            if (flatenCurves)
            {
                characterGlyph = new FlattenCurves(characterGlyph);
            }

            return characterGlyph;
        }

        public double GetAdvanceForCharacter(char character, char nextCharacterToKernWith)
        {
            return typeFace.GetAdvanceForCharacter(character, nextCharacterToKernWith) * currentEmScalling;
        }

        public double GetAdvanceForCharacter(char character)
        {
            return typeFace.GetAdvanceForCharacter(character) * currentEmScalling;
        }
    }
}
